﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SGS.Cards;
using SGS.Standard.Actor;
using SGS.Standard.Delegate;
using SGS.Standard.CardSelector;
using DataStruct;

namespace SGS.Standard.GameLogic
{
    internal class Strategy : GameLogicBase
    {
        #region Core - 锦囊加载器
        internal static void GL_OnUseLaterStrategy(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor,
            LaterStrategyCallback callback, int strategyDistance = int.MaxValue)
        {
            // 来源手牌检测
            actor.ActorPlayer.GameInfo.HasCard(actor.UsedCards.ToArray(), true, true);

            // 只能对一个人释放
            // 延时锦囊目标数量检测，最少有一个目标
            if (actor.TargetFirst.Count < 1)
            {
                RaiseNoticeMessageEvent("{0}必须要有一个目标", actor.AsSkillType);
                return;
            }

            // 距离Check
            var distance = PlayerDistanceCollection.Calc(GameContext.Current.PlayersCircle, actor.ActorPlayer);
            foreach (var target in actor.TargetFirst)
            {
                if (distance.GetDistance(actor.ActorPlayer, target) > strategyDistance)
                {
                    RaiseNoticeMessageEvent("{1} Only target Distance <= {0}", strategyDistance, actor.AsSkillType);
                    return;
                }
            }

            // 检测是否有相同的延时锦囊
            if (actor.TargetFirst[0].GameInfo.JudgeArea.Where(p => p.AsSkillType == actor.AsSkillType).Count() > 0)
            {
                RaiseNoticeMessageEvent("{1}的判定区已经有延时锦囊{0}", actor.AsSkillType, actor.TargetFirst[0].PlayerName);
                return;
            }

            // 能否成为目标检测，用于“谦逊”，“空城”，“帷幕”
            // GL_ValidStrategyTarget();

            // 移除手牌
            actor.ActorPlayer.GameInfo.TryRemoveCard(actor.UsedCards, true, true);

            callback(actor);

            // 卡牌丢弃
            Core.GL_UsedDiscard(actor.ActorPlayer, actor.UsedCards);
        }

        internal static void GL_OnStrategy(Player from, Player target, CardType type, List<Card> cards,
            StrategyCallback callback, int strategyDistance = int.MaxValue, bool useCard = true)
        {
            // 距离Check
            var distance = PlayerDistanceCollection.Calc(CurrentGameContext.PlayersCircle, from);

            if (distance.GetDistance(from, target) > strategyDistance)
            {
                RaiseNoticeMessageEvent("{1} Only target Distance <= {0}", strategyDistance, type);
                return;
            }

            // 能否成为目标检测，用于“谦逊”，“空城”，“帷幕”,目标无手牌等
            // GL_ValidStrategyTarget();

            if (useCard)
            {
                from.GameInfo.TryRemoveCard(cards);
                // from.GameInfo.OwnCards.Remove(cards);
            }

            // 询问无懈可击
            Ask.GL_AskWuXieKeJi();

            callback(from, target, cards);

            if (useCard)
            {
                Core.GL_UsedDiscard(from, cards);
            }
        }

        internal static void GL_OnUseAOEStrategy(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor, StrategyCallback callback, bool includeSelf = true)
        {
            // 移除卡牌
            actor.ActorPlayer.GameInfo.TryRemoveCard(actor.UsedCards);

            var node = GamePool.Current.PlayersCircle.GetCircleNode(actor.ActorPlayer);
            CircleNode<Player> dummy;
            if( includeSelf )
            {
                dummy = node.Previous;
            }
            else
            {
                dummy = node;
            }

            while(dummy.Next != node || includeSelf)
            {
                dummy = dummy.Next;
                if (includeSelf)
                {
                    includeSelf = false;
                }
                if (!dummy.Value.GameInfo.Live)
                {
                    continue;
                }
                else
                {
                    GL_OnStrategy(node.Value, dummy.Value, actor.AsSkillType, actor.UsedCards, callback, int.MaxValue, false);
                }
            }

            // 卡牌丢弃至牌堆
            Core.GL_UsedDiscard(actor.ActorPlayer, actor.UsedCards);
        }
        #endregion

        #region Single
        internal static void GL_WuZhongShengYou(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            RaiseNoticeMessageEvent("{0}对{0}使用了无中生有", actor.ActorPlayer.PlayerName);

            GL_OnStrategy(actor.ActorPlayer, actor.TargetFirst[0], CardType.WuZhongShengYou, actor.UsedCards, (from, target, cards) =>
            {
                RaiseNoticeMessageEvent("{0}从牌堆里摸了2张牌", actor.ActorPlayer.PlayerName);

                List<Card> gotcards = GameContext.Current.CardHeap.GetCards(2);
                actor.ActorPlayer.GameInfo.OwnCards.PushToEnd(gotcards);
            });
        }

        internal static void GL_JieDaoShaRen(Actor.HumanAnswerActor.UseCardActor answer)
        {
            if (answer.TargetFirst.Count != 1 || answer.TargetSecond.Count != 1)
            {
                RaiseNoticeMessageEvent("JieDaoShaRen target is not valid");
                return;
            }
            if (answer.TargetFirst[0] == answer.TargetSecond[0])
            {
                RaiseNoticeMessageEvent("can't attack self");
                return;
            }

            if (answer.TargetFirst[0].GameInfo.Weapon == null)
            {
                RaiseNoticeMessageEvent("target must has Weapon");
                return;
            }

            int distance = PlayerDistanceCollection.GetPlayerDistance(answer.TargetFirst[0], answer.TargetSecond[0]); // .Calc(answer.TargetFirst[0]).GetDistance( answer.TargetFirst[0], answer.TargetSecond[0] );
            if (answer.TargetFirst[0].GameInfo.AttackRange < distance)
            {
                RaiseNoticeMessageEvent(string.Format("{0} AttachRange is {1}, but Target {2} distance is {3}", answer.TargetFirst[0].PlayerName,
                    answer.TargetFirst[0].GameInfo.AttackRange, answer.TargetSecond[0].PlayerName, distance));
                return;
            }


            GL_OnStrategy(answer.ActorPlayer, answer.TargetFirst[0], CardType.JieDaoShaRen, answer.UsedCards, (from, target, cards) =>
            {
                var result = Ask.GL_AskBang(target, answer);
                switch (result.AnswerResult)
                {
                    case AskUseCardResult.AskResult.Used:
                        SGS.Standard.GameLogic.Basic.GL_Bang(answer, target, answer.TargetSecond[0].AsList(), result.UsedCard);
                        return;
                    case AskUseCardResult.AskResult.Skip:
                        break;
                    case AskUseCardResult.AskResult.Cancel:
                    default:
                        var gotcard = answer.TargetFirst[0].GameInfo.Weapon;
                        answer.TargetFirst[0].GameInfo.TryRemoveCard(gotcard);
                        from.GameInfo.OwnCards.PushToEnd(gotcard.AsList());
                        RaiseNoticeMessageEvent("{0}获得了{1}的武器{2}", from.PlayerName, target.PlayerName, cards.ToString());
                        break;
                }
            });
            throw new NotImplementedException();
        }

        internal static void GL_JueDou(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            if (actor.TargetFirst.Count != 1)
            {
                RaiseNoticeMessageEvent("Juedou Only target 1 player");
                return;
            }
            RaiseNoticeMessageEvent("{0}对{1}使用了决斗", actor.ActorPlayer.PlayerName, actor.TargetFirst[0].PlayerName);

            GL_OnStrategy(actor.ActorPlayer, actor.TargetFirst[0], CardType.JueDou, actor.UsedCards, (from, target, cards) =>
            {
                Player lastBangPlayer = from;

                while (true)
                {
                    var current = lastBangPlayer == from ? target : from;
                    var result = Ask.GL_AskBang(current, actor);
                    switch (result.AnswerResult)
                    {
                        case AskUseCardResult.AskResult.Cancel:
                            Core.GL_Damage(lastBangPlayer, lastBangPlayer == from ? target : from, DamageType.Default, cards);
                            return;
                        case AskUseCardResult.AskResult.Used:
                            Core.GL_UsedDiscard(current, result.UsedCard);
                            lastBangPlayer = lastBangPlayer == from ? target : from;
                            
                            break;
                        case AskUseCardResult.AskResult.Skip:
                            break;
                    }
                }

            });
        }

        internal static void GL_ShunShouQianYang(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            // 能否成为目标检测，用于“谦逊”，“帷幕”
            // GL_ValidStrategyTarget();

            CardSelectorMapping mapping = new CardSelectorMapping(actor.TargetFirst[0]);
            if (mapping.MappingResult.Count == 0)
            {
                throw new Exception("ShunShouQianYang target has no card");
            }

            RaiseNoticeMessageEvent("{0}对{1}使用顺手牵羊", actor.ActorPlayer.PlayerName, actor.TargetFirst[0].PlayerName);

            GL_OnStrategy(actor.ActorPlayer, actor.TargetFirst[0], CardType.ShunShouQianYang, actor.UsedCards,
                (from, target, cards) =>
                {
                    mapping = new CardSelectorMapping(actor.TargetFirst[0]);
                    if (mapping.MappingResult.Count == 0)
                    {
                        throw new Exception("ShunShouQianYang 目标已经没有牌可牵，跳过");
                    }

                    var resultItem = Ask.GL_AskSelectSomeCard(actor.ActorPlayer, mapping);
                    if (resultItem == null)
                    {
                        return;
                    }
                    else
                    {
                        if (actor.TargetFirst[0].GameInfo.TryRemoveCard(resultItem.TargetCard))
                        {
                            RaiseNoticeMessageEvent("{0}从{1}获得了一张牌", from.PlayerName, target.PlayerName);
                            actor.ActorPlayer.GameInfo.OwnCards.PushToEnd(resultItem.TargetCard.AsList());
                        }
                        else
                        {
                            throw new Exception("Selected Card is not target's card");
                        }
                    }
                }, 1);
        }

        internal static void GL_GuoHeChaiQiao(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            if (actor.TargetFirst.Count < 1)
            {
                throw new Exception("GuoHeChaiQiao must target 1 player");
            }

            // 能否成为目标检测，用于“谦逊”，“空城”，“帷幕”
            // GL_ValidStrategyTarget();

            CardSelectorMapping mapping = new CardSelectorMapping(actor.TargetFirst[0]);
            if (mapping.MappingResult.Count == 0)
            {
                throw new Exception("GuoHeChaiQiao target has no card");
            }

            RaiseNoticeMessageEvent("{0}对{1}使用过河拆桥", actor.ActorPlayer.PlayerName, actor.TargetFirst[0].PlayerName);

            GL_OnStrategy(actor.ActorPlayer, actor.TargetFirst[0], CardType.GuoHeChaiQiao, actor.UsedCards,
                (from, target, cards) =>
                {
                    mapping = new CardSelectorMapping(actor.TargetFirst[0]);
                    if (mapping.MappingResult.Count == 0)
                    {
                        throw new Exception("GuoHeChaiQiao 目标已经没有牌可拆，跳过");
                    }

                    var resultItem = Ask.GL_AskSelectSomeCard(actor.ActorPlayer, mapping);
                    if (resultItem == null)
                    {
                        return;
                    }
                    else
                    {
                        if (actor.TargetFirst[0].GameInfo.TryRemoveCard(resultItem.TargetCard))
                        {
                            RaiseNoticeMessageEvent("{0}的{1}被{2}拆除", target.PlayerName, resultItem.TargetCard.ToString(), from.PlayerName);
                            Core.GL_Discard(actor.TargetFirst[0], resultItem.TargetCard.AsList());
                        }
                        else
                        {
                            throw new Exception("Selected Card is not target's card");
                        }
                    }
                });
        }

        #endregion

        #region AoE
        internal static void GL_WuGuFengDeng(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            RaiseNoticeMessageEvent("{0}使用了五谷丰登", actor.ActorPlayer.PlayerName);

            var gotcards = GameContext.Current.CardHeap.GetCards(GamePool.Current.PlayersCircle.Where(p => p.GameInfo.Live).Count());
            CardSelectorMapping mapping = new CardSelectorMapping(gotcards.ToArray());

            GL_OnUseAOEStrategy(actor, (from, target, cards) =>
            {
                var selectedItem = Ask.GL_AskSelectSomeCard(target, mapping);
                if (selectedItem == null)
                {
                    // Cancel指令
                    return;
                }
                else
                {
                    selectedItem.Privilege = MappingPrivilege.Invalid;
                    target.GameInfo.OwnCards.PushToEnd(selectedItem.TargetCard.AsList());
                }
            }, true);

            var discards = mapping.MappingResult.Where(p => p.Privilege != MappingPrivilege.Invalid).Select(p => p.TargetCard);
            Core.GL_Discard(null, discards);
        }

        internal static void GL_TaoYuanJieYi(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            RaiseNoticeMessageEvent("{0}使用了桃源结义", actor.ActorPlayer.PlayerName);
            GL_OnUseAOEStrategy(actor, (from, target, cards) =>
            {
                Core.GL_Heal(from, target);
            }, true);
        }

        internal static void GL_NanManRuQin(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            RaiseNoticeMessageEvent("{0}使用了南蛮入侵", actor.ActorPlayer.PlayerName);
            GL_OnUseAOEStrategy(actor, (from, target, cards) =>
            {
                var result = Ask.GL_AskBang(target, actor);
                switch (result.AnswerResult)
                {
                    case AskUseCardResult.AskResult.Cancel:
                        Core.GL_Damage(from, target, DamageType.Default, cards);
                        break;
                    case AskUseCardResult.AskResult.Used:
                        RaiseNoticeMessageEvent("{0} 使用了杀", target.PlayerName);
                        Core.GL_UsedDiscard(target, result.UsedCard);
                        break;
                    case AskUseCardResult.AskResult.Skip:
                        break;
                }
            }, false);
        }

        internal static void GL_WanJianQiFa(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            RaiseNoticeMessageEvent("{0}使用了万箭齐发", actor.ActorPlayer.PlayerName);
            GL_OnUseAOEStrategy(actor, (from, target, cards) =>
            {
                var result = Ask.GL_AskMiss(target, actor);
                switch (result.AnswerResult)
                {
                    case AskUseCardResult.AskResult.Cancel:
                        Core.GL_Damage(from, target, DamageType.Default, cards);
                        break;
                    case AskUseCardResult.AskResult.Used:
                        RaiseNoticeMessageEvent("{0} 使用了闪", target.PlayerName);
                        Core.GL_UsedDiscard(target, result.UsedCard);
                        break;
                    case AskUseCardResult.AskResult.Skip:
                        break;
                }
            }, false);
        }

        #endregion

        #region LaterStrategy
        internal static void GL_LeBuSiShu(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            actor.AsSkillType = CardType.LeBuSiShu;
            if (actor.TargetFirst.Contains(actor.ActorPlayer))
            {

            }

            GL_OnUseLaterStrategy(actor, (x) =>
            {
                actor.TargetFirst[0].GameInfo.JudgeArea.Push(actor);
            });
        }

        internal static void GL_BingLiangCunDuan(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            actor.AsSkillType = CardType.BingLiangCunDuan;

            GL_OnUseLaterStrategy(actor, (x) =>
            {
                actor.TargetFirst[0].GameInfo.JudgeArea.Push(actor);
            }, 1);
        }

        internal static void GL_ShanDian(SGS.Standard.Actor.HumanAnswerActor.UseCardActor actor)
        {
            actor.AsSkillType = CardType.ShanDian;
            actor.TargetFirst.Clear();
            actor.TargetFirst.Add(actor.ActorPlayer);

            GL_OnUseLaterStrategy(actor, (x) =>
            {
                actor.TargetFirst[0].GameInfo.JudgeArea.Push(actor);
            }, 1);
        }
        #endregion
    }
}
